//! Recover statement parser (Go-style panic recovery with pattern matching)

use super::super::parse_expression;
use super::super::Parser;
use super::parse_statement;
use crate::ast::stmt::{RecoverArm, RecoverStmt};
use crate::error::{CompilerError, Result};
use crate::lexer::token::Token;
// Use the pattern parsing from expr_parser (public export)
use crate::parser::expr_parser::parse_pattern_or;

/// Parse recover statement
/// Syntax: recover err { pattern1 -> stmt1, pattern2 -> stmt2, _ -> stmt3 }
pub fn parse_recover_statement(parser: &mut Parser) -> Result<RecoverStmt> {
    parser.expect(&Token::Recover)?;

    // Parse error variable name
    let error_var = if let Some(Token::Identifier(var_name)) = parser.peek().map(|t| &t.token) {
        let name = var_name.clone();
        parser.advance()?;
        name
    } else {
        return Err(CompilerError::syntax(
            parser.current_location().line,
            parser.current_location().column,
            "Expected error variable name after 'recover'",
        ));
    };

    // Parse opening brace
    parser.expect(&Token::LeftBrace)?;

    let mut arms = Vec::new();

    // Parse pattern match arms
    while !parser.check(&Token::RightBrace) {
        if parser.is_at_end() {
            return Err(CompilerError::syntax(
                parser.current_location().line,
                parser.current_location().column,
                "Expected '}' to close recover block",
            ));
        }

        // Parse pattern
        let pattern = parse_pattern_or(parser)?;
        if pattern.is_none() {
            return Err(CompilerError::syntax(
                parser.current_location().line,
                parser.current_location().column,
                "Expected pattern in recover arm",
            ));
        }

        let pattern = pattern.unwrap();
        let pattern_location = parser.current_location();

        // Optional guard condition (if pattern)
        let guard = if parser.check(&Token::If) {
            parser.advance()?; // consume 'if'
            let guard_expr = parse_expression(parser)?;
            guard_expr
        } else {
            None
        };

        // Expect arrow '->'
        parser.expect(&Token::Arrow)?;

        // Parse handler body (statement)
        let body = parse_statement(parser)?;
        if body.is_none() {
            return Err(CompilerError::syntax(
                parser.current_location().line,
                parser.current_location().column,
                "Expected statement after '->' in recover arm",
            ));
        }

        arms.push(RecoverArm {
            pattern,
            guard,
            body: body.unwrap(),
            location: pattern_location,
        });

        // Skip optional comma and semicolons (for readability)
        parser.consume(&Token::Comma)?;
        while parser.consume(&Token::Semicolon)? {}

        // Check if we've reached the end of the recover block
        if parser.check(&Token::RightBrace) {
            break;
        }
    }

    parser.expect(&Token::RightBrace)?;

    Ok(RecoverStmt {
        error_var,
        arms,
        location: parser.current_location(),
    })
}
